Pytorch
什么是 PyTorch?
PyTorch 是一个基于 Python 的科学计算包,主要定位两类人群:
- NumPy 的替代品,可以利用 GPU 的性能进行计算。
- 深度学习研究平台拥有足够的灵活性和速度
Pytorch简介
PyTorch是一个基于Torch的Python开源机器学习库,用于自然语言处理等应用程序。它主要由Facebookd的人工智能小组开发,不仅能够 实现强大的GPU加速,同时还支持动态神经网络,这一点是现在很多主流框架如TensorFlow都不支持的。 PyTorch提供了两个高级功能:
- 具有强大的GPU加速的张量计算(如Numpy)
- 包含自动求导系统的深度神经网络
安装和使用
官网 选择对应cuda版本下载即可
1 | from __future__ import print_function |
数据类型和操作
Tensor(张量)
1 | # 构造一个5x3矩阵,不初始化。基本是0,或者+-10^-4之类 |
1 | # 连接矩阵,不同维度 Concatenates |
1 | # 输出第二列的数据 |
1 | # 加法 |
注意 任何使张量会发生变化的操作都有一个前缀 ‘_‘。例如:
x.copy_(y), x.t_(), 将会改变 x
PyTorch 自动微分
autograd 包是 PyTorch 中所有神经网络的核心。
autograd 软件包为 Tensors 上的所有操作提供自动微分。它是一个由运行定义的框架,这意味着以代码运行方式定义你的后向传播,并且每次迭代都可以不同。
TENSOR
torch.Tensor
是包的核心类。
如果将其属性 .requires_grad 设置为 True,则会开始跟踪针对 tensor 的所有操作。.requires_grad_( … ) 会改变张量的 requires_grad 标记。输入的标记默认为 False ,如果没有提供相应的参数。
完成计算后,您可以调用 .backward() 来自动计算所有梯度。
该张量的梯度将累积到 .grad 属性中。要停止 tensor 历史记录的跟踪,您可以调用 .detach(),它将其与计算历史记录分离,并防止将来的计算被跟踪。要停止跟踪历史记录(和使用内存),您还可以将代码块使用 with torch.no_grad(): 包装起来。
在评估模型时,这是特别有用,因为模型在训练阶段具有 requires_grad = True 的可训练参数有利于调参,但在评估阶段我们不需要梯度。(???)
另一个重要的类是Function。Tensor 和 Function 互相连接并构建一个非循环图,它保存整个完整的计算过程的历史信息。
每个张量都有一个 .grad_fn 属性保存着创建了张量的 Function 的引用,(如果用户自己创建张量,则g rad_fn 是 None )。
计算导数
你可以调用 Tensor.backward()。如果 Tensor 是标量(即它包含一个元素数据),则不需要指定任何参数backward(),但是如果它有更多元素,则需要指定一个gradient 参数来指定张量的形状。
神经网络的训练
定义网络
一个简单的前馈神经网络,它接收输入,让输入一个接着一个的通过一些层,最后给出输出。
通过 torch.nn 包来构建。一个 nn.Module 包括层和一个方法 forward(input) 它会返回输出(output)。
1 | import torch |
一个模型可训练的参数可以通过调用 net.parameters() 返回:
1 | params = list(net.parameters()) |
运行一次网络
1 | input = torch.randn(1, 1, 32, 32) |
反向传播计算各个位置梯度
把所有参数梯度缓存器置零,用随机的梯度来反向传播
1 | net.zero_grad() |
损失函数
一个损失函数需要一对输入:模型输出和目标,然后计算一个值来评估输出距离目标有多远。
有一些不同的损失函数在 nn 包中。一个简单的损失函数就是 nn.MSELoss ,这计算了均方误差。
可以调用包,也可以自己设计。
1 | output = net(input) |
使用loss反向传播更新梯度
查看梯度记录的地方
1 | input -> conv2d -> relu -> maxpool2d -> conv2d -> relu -> maxpool2d |
当我们调用 loss.backward(),整个图都会微分,而且所有的在图中的requires_grad=True 的张量将会让他们的 grad 张量累计梯度。
为了实现反向传播损失,我们所有需要做的事情仅仅是使用 loss.backward()。你需要清空现存的梯度,要不然将会和现存(上一轮)的梯度累计到一起。
1 | net.zero_grad() # zeroes the gradient buffers of all parameters |
查看某处梯度
1 | print(net.conv1.bias.grad) |
使用梯度和各种方法优化器更新参数
最简单的更新规则就是随机梯度下降。
1 | weight = weight - learning_rate * gradient |
我们可以使用 python 来实现这个规则:
1 | learning_rate = 0.01 |
尽管如此,如果你是用神经网络,你想使用不同的更新规则,类似于 SGD, Nesterov-SGD, Adam, RMSProp, 等。为了让这可行,我们建立了一个小包:torch.optim 实现了所有的方法。使用它非常的简单。
1 | import torch.optim as optim |
上面是一次训练
一般是按照一次多少batch训练,训练10次等.
或者考虑loss 稳定后结束,一般不使用loss小于某个值(因为不知道loss阈值是多少)
或许可以考虑K折交叉检验法(k-fold cross validation)
1 | for epoch in range(2): # loop over the dataset multiple times |
测试单个任务
分类任务,取最高的
1 | outputs = net(images) |
测试总误差
1 | correct = 0 |
各种初学者问题
In-place 正确性检查
所有的Variable都会记录用在他们身上的 in-place operations。如果pytorch检测到variable在一个Function中已经被保存用来backward,但是之后它又被in-place operations修改。当这种情况发生时,在backward的时候,pytorch就会报错。这种机制保证了,如果你用了in-place operations,但是在backward过程中没有报错,那么梯度的计算就是正确的。
对于不需要自动微分
=不需要计算梯度=手动计算值的
使用 someTensor.detach()
来更新
相关知识
欠拟合和过拟合判断
- 训练集和测试集都不好——欠拟合
- 训练集好,测试集不好——过拟合
多通道
一般是任务特征很多维度时,拓展描述参数用的。
比如:图像一般包含三个通道/三种原色(红色、绿色和蓝色)。 实际上,图像不是二维张量,而是一个由高度、宽度和颜色组成的三维张量。所以第三维通过通道表示。
https://zh.d2l.ai/chapter_convolutional-neural-networks/channels.html
多通道举例说明
1 | self.conv1 = nn.Conv2d(1, 6, 5) # 输入通道1,输出通道6,卷积核 5*5 |
$$
28=32-5+1
$$
初始1通道变6通道,意味着对初始的A数据,有6个初始值不同的5*5卷积核操作,产生6张图。需要参数6*5*5.
初始6通道变16通道,相当于将6通道变1通道,重复16次。6通道变1通道,通过6张图与由6个5*5卷积核组成的卷积核组作用,生成6张图,然后简单相加,变成1张。需要总参数16*6*5*5*5。相当于下图某些数据变成6和16:
BatchSize
https://blog.csdn.net/qq_34886403/article/details/82558399
- Batch Size定义:一次训练所选取的样本数。
- 由于矩阵操作,增加batch/行号。每行经过同一个网络,引起的就是输出行号增加。只需要对每行单独计算出来的误差进行sum或者mean得到一个误差值,就可以反向传播,训练参数。
- 简单来说就是平均了一个batch数据的影响,不会出现离谱的波动,方向比较准确。
- Batch Size的大小影响模型的优化程度和速度。同时其直接影响到GPU内存的使用情况,假如你GPU内存不大,该数值最好设置小一点。
- 没有Batch Size,梯度准确,只适用于小样本数据库
- Batch Size增大,梯度变准确。但是单个epoch的迭代次数减少了,参数的调整也慢了,假如要达到相同的识别精度,需要更多的epoch。
- Batch Size再增大,梯度已经非常准确,再增加Batch Size也没有用
- 虽然Batch Size增大,一遍的总次数变少,单步计算量增加。但是由于GPU并行操作,单步时间不会增加太多。
BatchNorm
Batch Normalization是将各层的输入进行归一化,使训练过程更快、更稳定的一种技术。在实践中,它是一个额外的层,我们通常添加在计算(卷积)层之后,在非线性(激活函数)之前。也有更先进的,比如layernorm。
BN层只是效果会变好,因为感受到了细节。不是有batch一定有BN层的意思。
各种不同的Loss
交叉熵和加权交叉熵
多用于多分类任务,预测值是每一类各自的概率。label为特定的类别
torch.nn.NLLLOSS通常不被独立当作损失函数,而需要和softmax、log等运算组合当作损失函数。
torch.nn.CrossEntropyLoss相当于softmax + log + nllloss。
预测的概率大于1明显不符合预期,可以使用softmax归一,取log后是交叉熵,取负号是为了符合loss越小,预测概率越大。
1 | # 4类权重是 1, 10, 100, 100 一般是与样本占比成反比 |
- size_average(该参数不建议使用,后续版本可能被废弃),该参数指定loss是否在一个Batch内平均,即是否除以N。默认为True
- reduce (该参数不建议使用,后续版本可能会废弃),首先说明该参数与size_average冲突,当该参数指定为False时size_average不生效,该参数默认为True。reduce为False时,对batch内的每个样本单独计算loss,loss的返回值Shape为[N],每一个数对应一个样本的loss。reduce为True时,根据size_average决定对N个样本的loss进行求和还是平均,此时返回的loss是一个数。
- reduction 该参数在新版本中是为了取代size_average和reduce参数的。
- 它共有三种选项’mean’,’sum’和’none’。
- ‘mean’为默认情况,表明对N个样本的loss进行求平均之后返回(相当于reduce=True,size_average=True);
- ‘sum’指对n个样本的loss求和(相当于reduce=True,size_average=False);
- ‘none’表示直接返回n分样本的loss(相当于reduce=False)
Focal Loss
相对于加权交叉熵不仅权重不需要计算,自动通过概率算,而且gamma=2按照平方缩小了,大样本的影响。
“蓝”线代表交叉熵损失。X轴即“预测为真实标签的概率”(为简单起见,将其称为pt)。举例来说,假设模型预测某物是自行车的概率为0.6,而它确实是自行车, 在这种情况下的pt为0.6。
Y轴是给定pt后Focal loss和CE的loss的值。
从图像中可以看出,当模型预测为真实标签的概率为0.6左右时,交叉熵损失仍在0.5左右。因此,为了在训练过程中减少损失,我们的模型将必须以更高的概率来预测到真实标签。换句话说,交叉熵损失要求模型对自己的预测非常有信心。但这也同样会给模型表现带来负面影响。
深度学习模型会变得过度自信, 因此模型的泛化能力会下降.
当使用γ> 1的Focal Loss可以减少“分类得好的样本”或者说“模型预测正确概率大”的样本的训练损失,而对于“难以分类的示例”,比如预测概率小于0.5的,则不会减小太多损失。因此,在数据类别不平衡的情况下,会让模型的注意力放在稀少的类别上,因为这些类别的样本见过的少,比较难分。
https://cloud.tencent.com/developer/article/1669261
https://blog.csdn.net/qq_34914551/article/details/105393989
https://ptorch.com/news/253.html
Pytorch.nn常用函数
torch.nn.Linear
$$
y=x*A^T+b
$$
设置网络中的全连接层的,需要注意在二维图像处理的任务中,全连接层的输入与输出一般都设置为二维张量,形状通常为[batch_size, size],不同于卷积层要求输入输出是四维张量。
in_features
指的是输入的二维张量的大小,即输入的[batch_size, size]中的size。
out_features
指的是输出的二维张量的大小,即输出的二维张量的形状为[batch_size,output_size],当然,它也代表了该全连接层的神经元个数。
torch.nn.ReLU()
$$
ReLU(x)=(x)^+=max(0,x)
$$
torch.nn.Sigmoid
$$
Sigmoid(x)=σ(x)= \frac{1}{1+exp(−x)}
$$
- torch.nn.Sigmoid()
- 是一个类。在定义模型的初始化方法中使用,需要在_init__中定义,然后再使用。
- torch.nn.functional.sigmoid():
- 可以直接在forward()里使用。eg.
A=F.sigmoid(x)
- 可以直接在forward()里使用。eg.
torch.cat
cat是concatnate的意思:拼接,联系在一起。
1 | C = torch.cat( (A,B),0 ) #按维数0拼接(竖着拼) |
torch.nn.BatchNorm2d
num_features – C from an expected input of size (N, C, H, W)
torch.nn.BatchNorm1d
Input: (N, C) or (N, C, L), where NN is the batch size, C is the number of features or channels, and L is the sequence length
Output: (N, C) or (N, C, L) (same shape as input)
Softmax函数和Sigmoid函数的区别
https://zhuanlan.zhihu.com/p/356976844
保存与读取
Save on GPU, Load on GPU
Save:
1 | torch.save(model.state_dict(), PATH) |
Load:
1 | device = torch.device("cuda") |
Remember that you must call model.eval()
to set dropout and batch normalization layers to evaluation mode before running inference. Failing to do this will yield inconsistent inference results.
误差的表示
训练参数怎么保存和读取
怎么表示数据
怎么反向梯度法训练
怎么使用GPU,怎么多GPU
在GPU上训练 就像你怎么把一个张量转移到GPU上一样,你要将神经网络转到GPU上。 如果CUDA可以用,让我们首先定义下我们的设备为第一个可见的cuda设备。
1 | device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") |
1 | net=Net() |
1 | input = torch.randn(1, 1, 32, 32) |
多GPU
如果你想要来看到大规模加速,使用你的所有GPU,请查看:数据并行性(https://pytorch.org/tutorials/beginner/blitz/data_parallel_tutorial.html)。PyTorch 60 分钟入门教程:数据并行处理
http://pytorchchina.com/2018/12/11/optional-data-parallelism/
可视化
网络结构可视化
自动
https://stackoverflow.com/questions/52468956/how-do-i-visualize-a-net-in-pytorch
或者手动drawio
误差实时可视化TensorBoard
https://www.cnblogs.com/sddai/p/14516691.html
原理: 通过读取保存的log文件来可视化数据
标量可视化
记录数据,默认在当前目录下一个名为’runs/‘的文件夹中。
1 | from torch.utils.tensorboard import SummaryWriter |
运行 tensorboard --logdir=runs/ --port 8123
在某端口打开,比如 https://127.0.0.1:6006
网络结构可视化
在tensorboard的基础上使用tensorboardX
1 | from tensorboardX import SummaryWriter |
PR曲线
1 | log_writer.add_pr_curve("pr_curve", label_batch, predict, epoch) |
x,y轴分别是recall和precision。应该有可能有矛盾的数据,或者网络分不开,对于不同的阈值,可以划分出PR图。
与ROC曲线左上凸不同的是,PR曲线是右上凸效果越好。
怎么分布式并行
需要进一步的研究学习
暂无
遇到的问题
- 矩阵或者向量的使用
- optimizer.step() # Does the update会自动循环吗?什么误差什么时候训练完毕呢?
开题缘由、总结、反思、吐槽~~
社会计算实验二,关于Meetup数据的预测性问题的解决
参考文献
https://pytorch-cn.readthedocs.io/zh/latest/
https://zh.d2l.ai/chapter_convolutional-neural-networks/channels.html
Exploring the Impact of Dynamic Mutual Influence on Social Event
Participation